package com.itguigu.glimail.search.thread;

import lombok.extern.slf4j.Slf4j;

import java.util.Objects;
import java.util.concurrent.*;

@Slf4j
public class ThreadTest {
    /**
     * 1、继承Thread类创建线程
     * 2、实现Runnable接口创建线程
     * 3.实现Callable接口通过FutureTask包装器来创建Thread线程(可以拿到返回结果,可以处理异常)
     * 4、使用ExecutorService、Callable、Future实现有返回结果的线程(线程池)线程池直接提交任务
     */
    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        try {
            log.info("main...start...");
//        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
//            log.info("当前线程:" + Thread.currentThread().getId());
//            int i = 10 / 2;
//            log.info("运行结果:" + i);
//        }, executor);
//            CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
//                log.info("当前线程:" + Thread.currentThread().getId());
//                int i = 10 / 0;
//                log.info("运行结果:" + i);
//                return i;
//            }, executor).whenComplete((integer, throwable) ->{
//                //虽然能得到异常信息,但是没法修改返回数据
//                log.info("异步任务完成了...结果是"+integer+"异常是"+throwable);
//            } ).exceptionally(throwable -> {
//                //感知异常.同时返回默认值
//                return 10;
//            });
            /**
             * 方法执行后的处理
             */
//            CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
//                log.info("当前线程:" + Thread.currentThread().getId());
//                int i = 10 / 4;
//                log.info("运行结果:" + i);
//                return i;
//            }, executor).handle((res, exception) ->{
//                if (res!=null) {
//                    return res * 2;
//                }
//                if (exception != null) {
//                    return 0;
//                }
//                return 1;
//            } );
            /**
             * 线程串行化
             * thenRunAsync不能获取到上一步的赶回结果 无返回值
             *
             * thenAcceptAsync 能接受上一步的结果  无返回值
             *
             *thenApplyAsync 能接受上一步的结果  有返回值
             */

//            CompletableFuture.supplyAsync(() -> {
//                log.info("当前线程:" + Thread.currentThread().getId());
//                int i = 10 / 4;
//                log.info("运行结果:" + i);
//                return i;
//            }, executor).thenAcceptAsync(System.out::println,executor);
//                    CompletableFuture.supplyAsync(() -> {
//                log.info("当前线程:" + Thread.currentThread().getId());
//                int i = 10 / 4;
//                log.info("运行结果:" + i);
//                return i;
//            }, executor).  thenRunAsync(() -> {
//                System.out.println("任务2启动了");
//
//            }, executor);

//            Integer integer = future.get();
//            log.info("main...end..." + integer);

//            CompletableFuture<String> f = CompletableFuture.supplyAsync(() -> {
//                log.info("当前线程:" + Thread.currentThread().getId());
//                int i = 10 / 4;
//                log.info("运行结果:" + i);
//                return i;
//            }, executor).thenApplyAsync(integer -> {
//                System.out.println(integer);
//                return "hello" + integer;
//            }, executor);
//            System.out.println(f.get()+"返回值");
//            CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
//                log.info("任务1启动:" + Thread.currentThread().getId());
//                int i = 10 / 4;
//                log.info("任务1结束:" + i);
//                return i;
//            }, executor);
//            CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
////                try {
//////                    Thread.sleep(3000);
////                } catch (InterruptedException e) {
////                    e.printStackTrace();
////                }
//                log.info("任务2启动:" + Thread.currentThread().getId());
//
//                log.info("任务2结束:");
//                return "hello";
//            }, executor);
//            future01.runAfterBothAsync(future02, ThreadTest::run, executor);\
//            future01.thenAcceptBothAsync(future02, ((f1, f2) -> {
//                System.out.println("任务3开始,之前的结果"+f1+"->>>>"+f2);
//            }), executor);


//            CompletableFuture<String> future = future01.thenCombineAsync(future02, (f1, f2) -> {
//                System.out.println("任务3开始,之前的结果" + f1 + "->>>>" + f2);
//                return f1 + "hello" + f2;
//            }, executor);
//            String s = future.get();
//            log.info(s);
            //两个任务  只要有一个完成  我们就执行任务3
            //runAfterEitherAsync  不感知结果  自己无业务返回值
//            future01.runAfterEitherAsync(future02, ThreadTest::run, executor);
            //acceptEitherAsync 感知结果  自己无业务返回值
//            future01.acceptEitherAsync(future02, integer -> {
//                run(); System.out.println(integer);;
//            }, executor);
            //acceptEitherAsync 感知结果  自己有业务返回值
//            CompletableFuture<String> future = future01.applyToEitherAsync(future01, o -> {
//
//                return o.toString() + "H啊哈";
//            }, executor);
//            System.out.println(future.get());
            CompletableFuture<String> futureImg = CompletableFuture.supplyAsync(() -> {
                log.info("查询图片信息");
                return "hello.jpg";
            }, executor);
            CompletableFuture<String> futureAttr = CompletableFuture.supplyAsync(() -> {
                log.info("查询商品属性");
                return "黑色+256G";
            }, executor);
            CompletableFuture<String> futureDesc = CompletableFuture.supplyAsync(() -> {
                log.info("查询商品介绍");
                return "小米";
            }, executor);
            //allOf
//            CompletableFuture<Void> future = CompletableFuture.allOf(futureImg, futureAttr, futureDesc);
            CompletableFuture<Object> future = CompletableFuture.anyOf(futureImg, futureAttr, futureDesc);
            Object o = future.get();
            System.out.println(o + "aVoid");

            log.info("main...end...");

        } finally {
            executor.shutdown();
        }


    }

    public static void thread(String[] args) throws ExecutionException, InterruptedException {

//        log.info("main...start...");
//        Thread01 thread01 = new Thread01();
//        thread01.start();
//        log.info("main...end...");
//        log.info("main...start...");
//        Runnable01 runnable01 = new Runnable01();
//        new Thread(runnable01).start();
//        log.info("main...end...");

//        log.info("main...start...");
//        Callable01 callable01 = new Callable01();
//        FutureTask<Integer> futureTask = new FutureTask<>(callable01);
//        new Thread(futureTask).start();
//        //get 等待整个线程执行完成,获取返回结果
//        Integer integer = futureTask.get();//阻塞等待
//        System.out.println(integer);
//        log.info("main...end...");
        //当前系统中池只有一个两个,每个异步任务,直接提交给线程池让他自己去执行
        /**
         *
         *
         *  int corePoolSize,核心线程数目[一直存在除非allowCoreThreadTimeOut]  线程池,创建好以后就准备就绪的线程数量,就等待异步任务去执行
         *  5个 Thread thread= new Thread()
         * int maximumPoolSize,最大线程数量 控制资源
         * long keepAliveTime,存活时间 如果当前线程数量大于core数量 释放空闲线程(不包活核心线程)
         * TimeUnit unit,时间单位
         * BlockingQueue<Runnable> workQueue,阻塞队列 如果任务有很多 就会将目前多的任务放在队列里
         * 只要有线程空闲  就会到队列里面取出心的任务执行
         * ThreadFactory threadFactory,线程的创建工厂
         * RejectedExecutionHandler handler)如果队列满了 按照我们的拒绝策略 拒绝执行任务         \
         *
         * *工作顺序:
         * * 1)、线程池创建，准备好core数量的核心线程，准备接受任务
         * * 1.1. core满了， 就将再进来的任务放入阻塞队列中。空闲的core就会自己去阻塞队列获取任务执行
         * * 1.2、 阻塞队列满了，就直接开新线程执行，最大只能开到max指定的数量
         * * 1.3. max满了就用RejectedExecut ionHdler拒绝任务
         * * 1.4、max都执行完成，有很多空闲.在指定的时间heepAliveTime以后， 释放max-core这些线程
         * *
         * new LinkedBlockingDeque<>():默认是Integer的最大值。内存不够
         *Executors.newCachedThreadPool();//core是0 所有都可回收
         * //        Executors.newFixedThreadPool();//core = max  固定大小  都不可回收
         * //        Executors.newScheduledThreadPool();//定时任务的
         * //        Executors.newSingleThreadScheduledExecutor();//单线程的线程池
         *
         *
         * */
//        Executors.newCachedThreadPool();//core是0 所有都可回收
//        Executors.newFixedThreadPool();//core = max  固定大小  都不可回收
//        Executors.newScheduledThreadPool();//定时任务的
//        Executors.newSingleThreadScheduledExecutor();//单线程的线程池
//        log.info("main...start...");
//        executorService.execute(new Runnable01());
//        log.info("main...end...");

        log.info("main...start...");
//        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 100, 10,
//                TimeUnit.SECONDS,
//                new LinkedBlockingDeque<>(10000),
//                Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
//        threadPoolExecutor.execute(new Runnable01());
        log.info("main...end...");

    }

    private static void run() {
        System.out.println("任务3开始  之前的结果");
    }


    public static class Thread01 extends Thread {
        @Override
        public void run() {
            log.info("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 2;
            log.info("运行结果:" + i);
        }
    }

    public static class Runnable01 implements Runnable {
        @Override
        public void run() {
            log.info("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 5;
            log.info("运行结果:" + i);
        }
    }

    public static class Callable01 implements Callable {
        @Override
        public Object call() throws Exception {
            log.info("当前线程:" + Thread.currentThread().getId());
            int i = 10 / 1;
            log.info("运行结果:" + i);
            return i;
        }
    }
}
